
package com.microboot.config;

import com.microboot.annotation.AutoPublishWS;
import lombok.extern.slf4j.Slf4j;
import org.apache.cxf.Bus;
import org.apache.cxf.jaxws.EndpointImpl;
import org.apache.cxf.transport.servlet.CXFServlet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.web.context.WebApplicationContext;

/**
 * 自动发布WebService端点的组件
 * 该类实现了ApplicationRunner接口，允许在Spring Boot应用启动后执行特定的操作
 * 主要负责扫描标记了@AutoPublishWS注解的Bean，并自动发布WebService端点
 */
@Slf4j
@Component
public class AutoPublishWSEndpoint implements ApplicationRunner {

    /**
     * CXF的总线，用于管理WebService的生命周期
     */
    @Autowired
    private Bus bus;

    /**
     * Web应用上下文，用于访问Bean的相关信息
     */
    @Autowired
    private WebApplicationContext webApplicationContext;

    /*
     * 配置CXFServlet的Servlet注册Bean
     *
     * @return ServletRegistrationBean对象，用于注册CXFServlet
     */
    //@Bean
    //public ServletRegistrationBean getRegistrationBean(){
    //    return new ServletRegistrationBean<>(new CXFServlet(),"/test/services_longx/*"); //webservic访问的父路径

        //默认示例说明：
        //不设置getRegistrationBean中的配置代码，默认路径是/services，如果需要修改，可以修改CXFServlet的构造函数的参数
        //注册的默认路径是/services，如果需要修改，可以修改CXFServlet的构造函数的参数
        //默认：return new ServletRegistrationBean<>(new CXFServlet(),"/services/*"); //webservic访问的父路径

        //自定义路径示例说明：
        //return new ServletRegistrationBean<>(new CXFServlet(),"/test/services_longx/*"); //webservic访问的父路径
        //http://localhost:8080/test/services_longx/MessageService?wsdl
    //}

    /**
     * 在应用启动后自动运行该方法
     * 主要用于扫描并发布WebService端点
     *
     * @param args 应用启动参数
     * @throws Exception 如果发布WebService端点时出现异常
     */
    @Override
    public void run(ApplicationArguments args) throws Exception {
        log.info("WebService开始发布CXF服务端点...");
        // 获取所有标记了AutoPublishWS注解的Bean名称
        String[] beanNames = webApplicationContext.getBeanNamesForAnnotation(AutoPublishWS.class);
        EndpointImpl endpoint = null;
        for (String beanName : beanNames) {
            // 获取Bean类型上的AutoPublishWS注解的发布路径
            String publishPath = webApplicationContext.getType(beanName).getAnnotation(AutoPublishWS.class).publishPath();
            // 创建并发布WebService端点
            endpoint = new EndpointImpl(bus, webApplicationContext.getBean(beanName));
            endpoint.publish(publishPath);
            log.info("WebService发布CXF服务端点成功!发布路径:{}", publishPath);
        }

        log.info("WebService发布CXF服务端点成功!");
    }
}